package com.ys.service.finance.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.dto.AddDto;
import com.ys.entity.base.CheckByGrid;
import com.ys.entity.business.TbBaseInfo;
import com.ys.entity.finance.TcwPartnerBankInfo;
import com.ys.entity.finance.TcwPaymentApply;
import com.ys.entity.finance.TcwPaymentApplyItem;
import com.ys.entity.flow.YspModel;
import com.ys.entity.sys.*;
import com.ys.enume.finance.TcwFinancialTransactionFlowEnum;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.mapper.finance.FinanceMapper;
import com.ys.mapper.finance.TcwPaymentApplyItemMapper;
import com.ys.mapper.finance.TcwPaymentApplyMapper;
import com.ys.service.business.TcwAccountDetailedForCompanyService;
import com.ys.service.finance.TcwFinancialTransactionFlowService;
import com.ys.service.finance.TcwPaymentApplyService;
import com.ys.service.flow.YspTaskService;
import com.ys.service.sys.CommonApiService;
import com.ys.util.CheckUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 付款申请单
 */
@Service("tcwPaymentApplyService")
public class TcwPaymentApplyServiceImpl implements TcwPaymentApplyService {
	private static final Logger logger = LoggerFactory.getLogger(TcwPaymentApplyServiceImpl.class);

	@Autowired
	private TcwPaymentApplyMapper tcwPaymentApplyMapper;

	@Autowired
	private TcwPaymentApplyItemMapper tcwPaymentApplyItemMapper;

	@Autowired
	private YspTaskService yspTaskService;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private FinanceMapper financeMapper;


	@Autowired
	private TcwAccountDetailedForCompanyService tcwAccountDetailedForCompanyService;

	@Autowired
	private TcwFinancialTransactionFlowService tcwFinancialTransactionFlowService;

	private final Long GRID = 42L;

	@Autowired
	private CommonApiService<TcwPaymentApply> commonApiService;

	/**
	 * 新增
	 */
	@Override
	public R add(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("新增传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TcwPaymentApply entity = JSON.parseObject(JSON.toJSONString(params), TcwPaymentApply.class);
		entity.setStatus(1);//状态
		entity.setEffectStock(0);//审批状态
		if(checkUtil.isNotNullByObject(params.get("premark"))){
			entity.setRemark(params.get("premark").toString());
		}

		//获取制单人信息
		TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setOrderby("A.CreateTime DESC").queryFirst();
		if(tsUserChange!=null){
			entity.setCreateChangeId(tsUserChange.getId());//制单人变更信息
		}else {
			return R.error("未查询到制单人信息！");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,entity);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}


		TcwPaymentApply oldEntity = new TcwPaymentApply().setBid(entity.getBid()).queryFirst();
		if(oldEntity!=null && oldEntity.getId()!=null){
			//修改
			entity.setId(oldEntity.getId());
			tcwPaymentApplyMapper.update(entity);
		}else {
			//新增
			tcwPaymentApplyMapper.insert(entity);
		}

		YsMenu ysMenu = new YsMenu().setId(menuId).queryFirst();
		if (ysMenu.getFlowModelId().longValue() != 0L) {
			YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
			String codeModel = yspModel.getCode();
			String createUserId = ShiroUtils.getUserId();
			yspTaskService.init(codeModel, entity.getBid(), createUserId);
			//审批流 =》 整单备注设置
			yspTaskService.setOtherParams(entity.getBid(),entity.getRemark(),params.get("orgName"));
		}
		//return R.ok(EditDto.closeAndReload());
		return R.ok(AddDto.gotoEdit("/web/finance/tcwPaymentApply/toEdit?bid=" + entity.getBid()));
	}


	/**
	 * 修改
	 */
	@Override
	public R update(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("修改传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TcwPaymentApply tcwPaymentApply = JSON.parseObject(JSON.toJSONString(params), TcwPaymentApply.class);
		if(checkUtil.isNotNullByObject(params.get("premark"))){
			tcwPaymentApply.setRemark(params.get("premark").toString());
		}

		// 验证状态
		YsProcInst ysProcInst = new YsProcInst().setBid(tcwPaymentApply.getBid()).queryFirst();
		if (ysProcInst == null) {
			return R.error("审批数据不存在，无法编辑");
		}
		/*
		else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.INIT.value) {
			return R.error("已流转，无法编辑");
		}
		 */

		//保存列表信息
		R saveItemRes = saveItem(params,tcwPaymentApply);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}

		tcwPaymentApplyMapper.update(tcwPaymentApply);
		//审批流 =》 整单备注设置
		yspTaskService.setOtherParams(tcwPaymentApply.getBid(),tcwPaymentApply.getRemark(),params.get("orgName"));
		//return R.ok();
		return R.ok(AddDto.gotoEdit("/web/finance/tcwPaymentApply/toEdit?bid=" + tcwPaymentApply.getBid()));
	}


	//保存列表信息
	public R saveItem(Map<String, Object> params,TcwPaymentApply tcwPaymentApply) throws Exception{
		//保存列表信息
		List<Map<String, Object>> subDataList = new ArrayList<>();
		if(params.get("subData")!=null){
			JSONArray subData = JSON.parseArray(params.get("subData").toString());
			CheckByGrid checkByGrid = checkParamsByGrid(subData,GRID,params);
			if(checkUtil.isNotNullByObject(checkByGrid.getErrMsg())){
				return R.error(checkByGrid.getErrMsg());
			}
			subDataList = checkByGrid.getSubDataList();
		}else {
			return R.error("列表信息为空！");
		}

		List<TcwPaymentApplyItem> oldList = new TcwPaymentApplyItem()
				.setPbid(tcwPaymentApply.getBid())
				.queryList();

		saveItemNoDelAll(oldList,subDataList,tcwPaymentApply.getBid());
		return R.ok();
	}


	public void saveItemNoDelAll(List<TcwPaymentApplyItem> oldList,List<Map<String, Object>> newList,String bid){
		if(oldList!=null && oldList.size()>0){
			for(TcwPaymentApplyItem oldItem:oldList){
				boolean isDel = true;
				for(Map<String, Object> newItem:newList){
					TcwPaymentApplyItem itemInfo = JSON.parseObject(JSON.toJSONString(newItem), TcwPaymentApplyItem.class);
					if(checkUtil.isNotNullByObject(itemInfo.getId())){
						if(itemInfo.getId().equals(oldItem.getId())){
							isDel = false;
						}
					}
				}
				if(isDel){
					tcwPaymentApplyItemMapper.deleteTrue(oldItem.getId());
				}
			}

			for (Map<String, Object> item:newList) {
				TcwPaymentApplyItem itemInfo = JSON.parseObject(JSON.toJSONString(item), TcwPaymentApplyItem.class);
				itemInfo.setStatus(1);
				itemInfo.setPbid(bid);
				if(checkUtil.isNotNullByObject(itemInfo.getId())){
					//修改
					tcwPaymentApplyItemMapper.update(itemInfo);
				}else {
					//新增
					itemInfo.setAnnexFile("0个附件");
					itemInfo.setReceiptAnnexFile("0个附件");
					tcwPaymentApplyItemMapper.insert(itemInfo);
				}
			}

		}else {
			for (Map<String, Object> item:newList) {
				TcwPaymentApplyItem itemInfo = JSON.parseObject(JSON.toJSONString(item), TcwPaymentApplyItem.class);
				itemInfo.setStatus(1);
				itemInfo.setPbid(bid);
				//新增
				itemInfo.setAnnexFile("0个附件");
				itemInfo.setReceiptAnnexFile("0个附件");
				tcwPaymentApplyItemMapper.insert(itemInfo);
			}
		}


	}


	//删除
	@Override
	@Transactional
	public R del(Long id) throws Exception{
		if (id == null) {
			return R.error("ID不能为空");
		}
		TcwPaymentApply entity = new TcwPaymentApply().setId(id).queryFirst();
		if (entity.getEffectStock() == FlowEnum.EffectStock.EFFECTED.value) {
			return R.error("已生效数据无法删除");
		}
		// 验证是否制单人
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setId(entity.getCreateChangeId()).queryFirst();
		if (!tsUserChange.getUserId().equals(loginUserId) && !"admin".equals(loginUserId)) {
			return R.error("非制单人，无法删除");
		}
		//删除
		tcwPaymentApplyMapper.deleteTrue(id);
		//删除列表信息
		financeMapper.deleteTcwPaymentApplyItemByPbid(entity.getBid());
		//删除流程
		yspTaskService.flowDelete(entity.getBid(), loginUserId);
		return R.ok();
	}



	//删除列表
	@Override
	@Transactional
	public R toDelByItem(Long id) throws Exception{
		tcwPaymentApplyItemMapper.deleteTrue(id);
		return R.ok();
	}

	/**
	 * 流转通过
	 */
	@Override
	@Transactional
	public R flowPass(Long id, String loginUserId) throws Exception {

		TcwPaymentApply entity = new TcwPaymentApply().setId(id).queryFirst();
		Flow f = yspTaskService.flowPass(entity.getBid(), loginUserId);
		if (f.getCode() == Flow.Code.FAILED.value) {
			return R.error(f.getMsg());
		} else {
			if (f.getState() == Flow.State.FINISH.value) {
				return flowFinish(entity.getBid());
			}
			return R.ok();
		}
	}

	/**
	 * 流转结束
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R flowFinish(String bid) throws Exception {

		TcwPaymentApply entity = new TcwPaymentApply().setBid(bid).queryFirst();
		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.FINISH.value) {
			return R.error();
		}
		Date theDate = new Date();
		entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);
		entity.setUpdateTime(theDate);

		if(entity.getAccountingTime()==null){//如果记账时间为空，则赋值成审核时间
			entity.setAccountingTime(theDate);
		}

		//查询子件信息
		List<Map<String, Object>> itemList = new TcwPaymentApplyItem()

				.addLeftJoin("THR_OperateCompanyApply C ON C.Vgsbm = A.Vgsbm ")//运营公司管理表
				.addField("C.Vgsjc AS vgsjc")//运营公司简称

				.addLeftJoin("TB_BaseInfo T ON T.Bid = A.TransactionTypeBid ")//财务交易类型
				.addField("T.Vremark AS vremark")//交易类型

				.addLeftJoin("TCW_PartnerBankInfo PB ON PB.Id = A.PartnerBankInfoId ")//员工银行账户管理
				.addField("PB.Vid AS vid")//合作商账户编码
				.addField("PB.PartnerName AS partnerName")//合作商名称
				.addField("PB.Vkhh AS vkhh")//合作商开户行
				.addField("PB.Vyhzh AS vyhzh")//合作商银行账号

				.setPbid(bid)
				.queryMap();

		//新增流水相关
		for (int i=0;i<itemList.size();i++){
			Map<String, Object> item = itemList.get(i);
			//新增业务交易流水
			R res1 = tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyWithJcNoTrigger(item.get("vgsbm").toString(),item.get("vgsjc").toString(),
					item.get("vid").toString(), item.get("partnerName").toString(), item.get("vremark").toString(),
					new BigDecimal(item.get("paymentAmount").toString()).negate(),entity.getCreateTime(), theDate,"付款申请单："+bid+"，备注："+(checkUtil.isNotNullByObject(item.get("remark"))?item.get("remark").toString():""),
					bid,entity.getAccountingTime());

			if(res1.getCode().equals(R.Code.FAILED.value)){//失败
				logger.info("新增业务交易流水失败:"+res1.getMsg()+"\n"+item);
				throw new IllegalArgumentException(res1.getMsg());
				//return R.error(res1.getMsg());
			}

			//新增财务交易流水
			R res2 = tcwFinancialTransactionFlowService.add(true, entity.getCompanyBankInfoId(), item.get("transactionTypeBid").toString(),
					item.get("partnerName").toString(), item.get("vkhh").toString(), item.get("vyhzh").toString(), new BigDecimal(item.get("paymentAmount").toString()).negate(),
					entity.getCreateTime(), theDate, entity.getAccountingTime(), "付款申请单："+bid+"，备注："+(checkUtil.isNotNullByObject(item.get("remark"))?item.get("remark").toString():""),
					TcwFinancialTransactionFlowEnum.FromType.TCW_PaymentApplyItem.value, Long.parseLong(item.get("id").toString()));

			if(res2.getCode().equals(R.Code.FAILED.value)){//失败
				logger.info("新增财务交易流水失败:"+res2.getMsg()+"\n"+item);
				throw new IllegalArgumentException(res2.getMsg());
				//return R.error(res2.getMsg());
			}

		}

		//修改信息
		tcwPaymentApplyMapper.update(entity);

		return R.ok();
	}

	/**
	 * 参数验证
	 */
	public String checkParams(Map<String, Object> params, Long menuId) throws Exception {
		//获取pc字段数据
		List<YsCol> listField = new YsCol()
				.where("A.MenuId = "+menuId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		//验证必填字段的非空；其他字段的长度限制、类型
		String backMsg = checkUtil.checkTableColLengthAndDataType("TCW_PaymentApply",listField,params,ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1);
		return backMsg;
	}


	/**
	 * 子表参数验证
	 */
	public CheckByGrid checkParamsByGrid(JSONArray subDataArray, Long gridId, Map<String, Object> params) throws Exception {
		CheckByGrid checkByGrid = new CheckByGrid();
		//获取pc字段数据
		List<YsGridCol> listField = new YsGridCol()
				.setGridId(gridId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		String backMsg = "";
		List<Map<String, Object>> subDataList = new ArrayList<>();

		if(subDataArray!=null && subDataArray.size()>0){
			for (int i = 0; i < subDataArray.size(); i++) {
				JSONObject jsonObject = subDataArray.getJSONObject(i);
				Map<String, Object> paramsNewByRecord = new HashMap<>();
				for (String key : jsonObject.keySet()) {
					paramsNewByRecord.put(key, jsonObject.get(key));
				}
				subDataList.add(paramsNewByRecord);
			}
			//验证
			for(int i = 0;i<subDataList.size();i++){
				String backMsgByRow = "";
				Map<String, Object> subData = subDataList.get(i);
				//验证必填字段的非空；其他字段的长度限制、类型
				backMsgByRow += checkUtil.checkTableColLengthAndDataTypeByGrid(
						"TCW_PaymentApplyItem",
						listField,
						subData,
						ysColItem->
								ysColItem.getCode().equals("vgsbm")//运营公司编码
										|| ysColItem.getCode().equals("transactionTypeBid")//业务交易类型
										|| ysColItem.getCode().equals("paymentAmount")//付款金额
										|| ysColItem.getCode().equals("partnerBankInfoId")//合作商银行账户
				);

				if(checkUtil.isNotNullByObject(backMsgByRow)){
					backMsg += "列表第" + (i+1) + "行，" + backMsgByRow;
				}
			}
		}else{
			backMsg = "列表信息为空";
		}
		checkByGrid.setErrMsg(backMsg);
		checkByGrid.setSubDataList(subDataList);

		return checkByGrid;
	}



	//批量导入
	@Override
	@Transactional
	public R importInfo(String rows,Long menuId) throws Exception{
		logger.info("导入的数据：\n" + rows);

		JSONArray detailList = JSON.parseArray(rows);
		String bid = "";
		for(int i=0;i<detailList.size();i++) {
			JSONObject info = detailList.getJSONObject(i);
			Map infoMap = JSONObject.parseObject(info.toString(), Map.class);
			//验证导入字段

			//验证：运营公司编码
			if (checkUtil.isNullByObject(infoMap.get("vgsbm"))) {
				return R.error("数据运营公司编码为空");
			}

			//验证：交易类型
			if (checkUtil.isNullByObject(infoMap.get("vremark"))) {
				return R.error("交易类型为空");
			}

			TbBaseInfo tbBaseInfo = new TbBaseInfo().setVReMark(infoMap.get("vremark").toString().trim()).queryFirst();
			if(tbBaseInfo==null || tbBaseInfo.getId()==null){
				return R.error("未在系统中查询到对应的交易类型");
			}

			//验证：收款金额
			if (checkUtil.isNullByObject(infoMap.get("paymentAmount"))) {
				return R.error("付款金额为空");
			}
			if (!checkUtil.isDecimal(infoMap.get("paymentAmount").toString().trim(),"2")) {
				return R.error("付款金额应为2位小数");
			}

			//验证：合作商账户
			if (checkUtil.isNullByObject(infoMap.get("pbvid"))) {
				return R.error("合作商账户编码为空");
			}
			TcwPartnerBankInfo tcwPartnerBankInfo = new TcwPartnerBankInfo().setVid(infoMap.get("pbvid").toString().trim()).queryFirst();
			if(tcwPartnerBankInfo==null || tcwPartnerBankInfo.getId()==null){
				return R.error("未在系统中查询到对应的合作商账户信息");
			}


			//获取制单人信息
			TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setOrderby("A.CreateTime DESC").queryFirst();
			if(tsUserChange ==null || tsUserChange.getId()==null){
				return R.error("未查询到制单人信息！");
			}

			TcwPaymentApply entity = new TcwPaymentApply();
			if ("".equals(bid)){
				if (checkUtil.isNullByObject(infoMap.get("bid"))) {
					bid = commonApiService.getCommonNextBid(menuId);
					entity.setBid(bid);
					entity.setCreateChangeId(tsUserChange.getId());
					entity.setStatus(0);
					entity.setEffectStock(FlowEnum.EffectStock.NOT_EFFECT.value);
					tcwPaymentApplyMapper.insert(entity);
				}else {
					bid = infoMap.get("bid").toString();
				}
			}

			TcwPaymentApplyItem itemInfo = new TcwPaymentApplyItem();
			itemInfo.setPbid(bid);
			itemInfo.setStatus(0);
			if (checkUtil.isNotNullByObject(infoMap.get("sRemark"))) itemInfo.setRemark(infoMap.get("sRemark").toString());
			itemInfo.setVgsbm(infoMap.get("vgsbm").toString().trim());
			itemInfo.setTransactionTypeBid(tbBaseInfo.getBid());
			itemInfo.setPaymentAmount(new BigDecimal(infoMap.get("paymentAmount").toString().trim()));
			itemInfo.setPartnerBankInfoId(tcwPartnerBankInfo.getId());
			itemInfo.setAnnexFile("0个附件");
			itemInfo.setReceiptAnnexFile("0个附件");
			tcwPaymentApplyItemMapper.insert(itemInfo);

		}



		return R.ok(bid);
	}



	//获取列表数据
	@Override
	@Transactional
	public Map<String,Object> getExtraParam( String bid) throws Exception{
		Map<String,Object> entity = new TcwPaymentApply()

				.addField("A.Remark AS premark")
				.addLeftJoin("YS_ProcInst P ON P.Bid = A.Bid ")
				.addField("FORMAT(P.UpdateTime, 'yyyy-MM-dd HH:mm:ss') AS auditingTime")//审核时间

				.addLeftJoin("TB_CompanyBankInfo CB ON CB.Id = A.CompanyBankInfoId ")//公司银行账户管理表
				.addField("CB.Vid AS vid")//账号编码
				.addField("CB.Vyhzhmc AS vyhzhmc")//付款账号名称
				.addField("CB.Vkhh AS vkhh")//付款开户行
				.addField("CB.Vyhzh AS vyhzh")//银行账户编码
				.addLeftJoin("TB_CompanyInfo tbc on  tbc.Vid = CB.CompanyInfoVid")
				.addField("tbc.Vname AS orgName")//所属公司

				.addLeftJoin("(SELECT ISNULL(SUM(S.PaymentAmount),0) AS paymentAmount,S.Pbid FROM TCW_PaymentApplyItem S GROUP BY S.Pbid) B ON B.Pbid = A.Bid")
				.addField("B.paymentAmount AS paymentAmountTotal")//付款总金额

				.setBid(bid)
				.queryFirstMap();

		return entity;
	}
	//获取子列表数据
	@Override
	@Transactional
	public List<Map<String, Object>> getItemList( String bid) throws Exception{
		List<Map<String, Object>> itemList = new TcwPaymentApplyItem()

				.addLeftJoin("THR_OperateCompanyApply C ON C.Vgsbm = A.Vgsbm ")//运营公司管理表
				.addField("C.Vgsjc AS vgsjc")//运营公司简称

				.addLeftJoin("TB_BaseInfo T ON T.Bid = A.TransactionTypeBid ")//财务交易类型
				.addField("T.Vremark AS vremark")//交易类型

				.addLeftJoin("TCW_PartnerBankInfo PB ON PB.Id = A.PartnerBankInfoId ")//员工银行账户管理
				.addField("PB.Vid AS vid")//合作商账户编码
				.addField("PB.PartnerName AS partnerName")//合作商名称
				.addField("PB.Vkhh AS vkhh")//合作商开户行
				.addField("PB.Vyhzh AS vyhzh")//合作商银行账号

				.setPbid(bid)
				.queryMap();
		return itemList;
	}

}
